package service

import (
	"context"
	"errors"
	"math/rand"
	"regexp"
	"time"
	"user-srv/basic/global"
	"user-srv/basic/proto/user"
	__ "user-srv/basic/proto/user"
	"user-srv/handler/model"
	"user-srv/pkg"

	"gorm.io/gorm"
)

type Server struct {
	user.UnimplementedUserServer
}

// 登录
func (s *Server) Login(_ context.Context, in *__.LoginReq) (*__.LoginResp, error) {
	user := model.User{
		Phone:    in.Phone,
		Password: pkg.Md5(in.Password),
	}

	global.DB.Where("phone = ?", in.Phone).Find(&user)
	if user.ID == 0 {
		return nil, errors.New("当前用户不存在,请前去注册")
	}

	if in.Password != "" {

		count, _ := global.Rdb.Get(global.Ctx, "passwordNum"+in.Phone).Result()
		if count >= "3" {
			return nil, errors.New("密码错误次数超过三次,封禁两小时")
		}

		global.Rdb.Set(global.Ctx, "Password"+in.Phone, in.Password, time.Hour*1)

		incr := global.Rdb.Incr(global.Ctx, "passwordNum"+in.Phone)
		if incr.Val() == 1 {
			global.Rdb.Expire(global.Ctx, "passwordNum"+in.Phone, time.Hour*2)
		}
		if pkg.Md5(in.Password) != user.Password {
			return nil, errors.New("密码错误,请重新输入")
		}
	} else {
		result, _ := global.Rdb.Get(global.Ctx, "smsCode"+in.Phone).Result()
		if result != in.SendCode {
			return nil, errors.New("短信验证码错误,请重新输入")
		}
	}
	return &__.LoginResp{
		Id: int64(user.ID),
	}, nil
}

// 注册
func (s *Server) Register(_ context.Context, in *__.RegisterReq) (*__.RegisterResp, error) {
	user := model.User{
		Phone:    in.Phone,
		Password: pkg.Md5("123"),
	}
	global.DB.Where("phone = ?", in.Phone).Find(&user)
	if user.ID != 0 {
		return nil, errors.New("当前用户已存在,请前去登录")
	}

	result, _ := global.Rdb.Get(global.Ctx, "smsCode"+in.Phone).Result()
	if result != in.SendCode {
		return nil, errors.New("短信验证码错误,请重新输入")
	}

	global.DB.Create(&user)
	return &__.RegisterResp{
		Id: int64(user.ID),
	}, nil
}

// 短信验证

var phone = regexp.MustCompile(`^1[3-9]\d{9}$`)

func isPhone(Phone string) bool {
	return phone.MatchString(Phone)
}

func (s *Server) SendSms(_ context.Context, in *__.SendSmsReq) (*__.SendSmsResp, error) {

	if !isPhone(in.Phone) {
		return nil, errors.New("手机号格式错误,请重新输入")
	}

	result, _ := global.Rdb.Get(global.Ctx, "MinNumber"+in.Phone).Result()
	if result >= "1" {
		return nil, errors.New("一分钟内只能发送一次验证码")
	}

	code := rand.Intn(9000) + 1000

	global.Rdb.Set(global.Ctx, "smsCode"+in.Phone, code, time.Hour*1)

	incr := global.Rdb.Incr(global.Ctx, "MinNumber"+in.Phone)

	if incr.Val() == 1 {
		global.Rdb.Expire(global.Ctx, "MinNumber"+in.Phone, time.Minute*1)
	}

	return &__.SendSmsResp{}, nil
}

// 完善信息
func (s *Server) UserInfo(_ context.Context, in *__.UserInfoReq) (*__.UserInfoResp, error) {
	user := model.User{
		Model:    gorm.Model{ID: uint(in.Id)},
		NickName: in.NickName,
		Avatar:   in.Avatar,
		RelaName: in.RelaName,
		Status:   int(in.Status),
		Balance:  in.Balance,
	}
	global.DB.Updates(&user)
	return &__.UserInfoResp{
		Id:       int64(user.ID),
		Phone:    user.Phone,
		Password: user.Password,
		NickName: user.NickName,
		Avatar:   user.Avatar,
		RelaName: user.RelaName,
		Status:   int64(user.Status),
		Balance:  user.Balance,
	}, nil
}

// 找回密码
func (s *Server) UserNewPassword(_ context.Context, in *__.UserNewPasswordReq) (*__.UserNewPasswordResp, error) {

	user := model.User{
		Phone: in.Phone,
	}

	global.DB.Where("phone = ?", in.Phone).Find(&user)
	if user.ID == 0 {
		return nil, errors.New("当前用户不存在,请前去注册")
	}

	result, _ := global.Rdb.Get(global.Ctx, "smsCode"+in.Phone).Result()
	if result != in.SendCode {
		return nil, errors.New("短信验证码错误,请重新输入")
	}

	if in.Password != in.NewPassword {
		return nil, errors.New("两次密码不一致")
	}

	if pkg.Md5(in.NewPassword) == user.Password {
		return nil, errors.New("新旧密码一致")
	}

	user.Password = pkg.Md5(in.NewPassword)

	global.DB.Updates(&user)

	return &__.UserNewPasswordResp{
		Id: int64(user.ID),
	}, nil
}

// 用户首页
func (s *Server) UserIndex(_ context.Context, in *__.UserIndexReq) (*__.UserIndexResp, error) {

	user := model.User{
		Model: gorm.Model{ID: uint(in.Id)},
	}
	global.DB.Find(&user)

	return &__.UserIndexResp{
		Id:       int64(user.ID),
		Phone:    user.Phone,
		Password: user.Password,
		NickName: user.NickName,
		Avatar:   user.Avatar,
		RelaName: user.RelaName,
		Status:   int64(user.Status),
		Balance:  user.Balance,
	}, nil
}
